package com.burst.reptile.framework.websocket.sendone;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.burst.reptile.common.utils.DateUtil;
import com.burst.reptile.common.utils.ToolUtil;
import com.burst.reptile.framework.config.SpringContextHolder;
import com.burst.reptile.framework.websocket.WebSocketConfigurator;
import com.burst.reptile.modular.system.entity.SysUser;
import com.burst.reptile.modular.system.mapper.SysUserMapper;
import com.burst.reptile.modular.zp.entity.ZpChatList;
import com.burst.reptile.modular.zp.entity.ZpChatMsg;
import com.burst.reptile.modular.zp.mapper.ZpChatListMapper;
import com.burst.reptile.modular.zp.mapper.ZpChatMsgMapper;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 一对一发送消息
 * 
 * @author wujin
 *
 * @date: 2020-9-1 13:46:49
 */
@ServerEndpoint(value = "/app/chat/one/{username}", configurator = WebSocketConfigurator.class)
@Component
@Slf4j
public class MyOneToOneServer {

	private ZpChatListMapper chatListMapper = SpringContextHolder.getBean(ZpChatListMapper.class);

	private ZpChatMsgMapper chatMsgMapper = SpringContextHolder.getBean(ZpChatMsgMapper.class);

	private SysUserMapper userMapper = SpringContextHolder.getBean(SysUserMapper.class);
	
	private MyOneServer myOneServer = SpringContextHolder.getBean(MyOneServer.class);

	/**
	 * 用于存放所有在线客户端
	 */
	private static Map<String, Session> clients = new ConcurrentHashMap<>();

	@OnOpen
	public void onOpen(Session session, @PathParam(value = "username") String userName, EndpointConfig endpointConfig) {
		clients.put(userName, session);
	}

	@OnClose
	public void onClose(Session session, @PathParam(value = "username") String userName, CloseReason closeReason) {
		clients.remove(userName);
		long[] split = StrUtil.splitToLong(userName, "_");
		long userId = split[0];
		long anotherId = split[1];
		List<ZpChatList> selectList = chatListMapper
				.selectList(new QueryWrapper<ZpChatList>().eq("user_id", userId).eq("another_id", anotherId));
		if (ToolUtil.isNotEmpty(selectList)) {
			selectList.forEach(i -> {
				i.setUserOnline("0");
				chatListMapper.updateById(i);
			});
		}
	}

	@OnError
	public void onError(Session session, @PathParam(value = "username") String userName, Throwable throwable) {
		if (clients.get(userName) != null) {
			log.info("发生了错误,移除客户端: {},{}", userName, throwable.getMessage());
			clients.remove(userName);
			long[] split = StrUtil.splitToLong(userName, "_");
			long userId = split[0];
			long anotherId = split[1];
			List<ZpChatList> selectList = chatListMapper
					.selectList(new QueryWrapper<ZpChatList>().eq("user_id", userId).eq("another_id", anotherId));
			if (ToolUtil.isNotEmpty(selectList)) {
				selectList.forEach(i -> {
					i.setUserOnline("0");
					chatListMapper.updateById(i);
				});
			}
		}
	}

	@OnMessage
	public void onMessage(String message) {
		Message msg = JSONObject.parseObject(message, Message.class);
		this.sendTo(msg);
	}

	/**
	 * 发送消息
	 *
	 * @param message 消息对象
	 */
	private void sendTo(Message message) {
		Session s = clients.get(message.getUserName());
		Long sendUserId = message.getSendUserId();
		Long userId = message.getUserId();
		// 创建聊天列表
		ZpChatList chat = null;
		List<ZpChatList> selectList = chatListMapper
				.selectList(new QueryWrapper<ZpChatList>().eq("user_id", userId).eq("another_id", sendUserId));
		if (ToolUtil.isEmpty(selectList)) {
			chat = new ZpChatList();
			chat.setUserId(userId);
			chat.setAnotherId(sendUserId);
			chat.setUnread(0);
		} else {
			chat = selectList.get(0);
		}
		ZpChatMsg msg = new ZpChatMsg();
		msg.setContent(message.getMessage());
		msg.setLatest("0");
		msg.setMtype(message.getType());
		msg.setRecUserId(userId);
		msg.setUserId(sendUserId);

		if (ToolUtil.isNotEmpty(s)) {
			try {
				Map<String, Object> map = new HashMap<>();
				map.put("userId", sendUserId);
				SysUser selectById = userMapper.selectById(sendUserId);
				if (ToolUtil.isNotEmpty(selectById)) {
					map.put("avatar", selectById.getAvatar());
					map.put("nickName", selectById.getNickName());
				}
				map.put("content", message.getMessage());
				map.put("time", DateUtil.timeToFormatchat(LocalDateTime.now()));
				s.getBasicRemote().sendText(JSONObject.toJSONString(map));
				chat.setUserOnline("1");
			} catch (IOException e) {
				log.info("客户端发送消息: {}，失败", message.getUserName());
			}
		} else {
			chat.setUserOnline("0");
			chat.setUnread(chat.getUnread() + 1);
		}
		if (StrUtil.isNotEmpty(chat.getLid())) {
			chatListMapper.updateById(chat);
		} else {
			chatListMapper.insert(chat);
		}
		// 更新上一次最后一条消息
		List<ZpChatMsg> msgs = chatMsgMapper.selectList(new QueryWrapper<ZpChatMsg>().eq("latest", "0")
				.and(i -> i.eq("user_id", sendUserId).eq("rec_user_id", userId)).or().eq("user_id", userId)
				.eq("rec_user_id", sendUserId));
		if (ToolUtil.isNotEmpty(msgs)) {
			msgs.forEach(i -> {
				i.setLatest("1");
				chatMsgMapper.updateById(i);
			});
		}
		chatMsgMapper.insert(msg);
		myOneServer.sendTo(userId.toString());
	}
}
